use super::*;
use std::path::Path;

#[derive(Debug)]
pub enum Action {
    Normal,
    Clean,
}

#[derive(Debug)]
pub struct Context {
    pub current_image_path: PathBuf,
    pub action: Action,
    pub domain: String,
    pub directory: PathBuf,
    pub desktop_cfg_path: PathBuf,
    pub if_edit: bool,
    pub remove_config: bool,
}
impl Context {
    pub fn from_cli() -> eyre::Result<Self> {
        use clap::*;

        let matches = command!()
            .arg(
                Arg::new("not_check")
                    .short('n')
                    .long("notcheck")
                    .help("Don't check the date and download the wallpaper and change the current wallpaper to it.")
                    .action(ArgAction::SetTrue),
            )
            .arg(
                Arg::new("remove_config")
                    .short('r')
                    .long("removeconfig")
                    .help("Use the default config at this run and the config will be reset to the default after this run.")
                    .action(ArgAction::SetTrue),
            )
            .subcommand(Command::new("clean").about("clean the wallpapers that are out-dated"))
            .get_matches();

        let remove_config = matches.get_flag("remove_config");

        let mut context = Self::new(remove_config)?;

        context.if_edit |= matches.get_flag("not_check");

        if matches.subcommand_matches("clean").is_some() {
            context.action = Action::Clean;
        }

        Ok(context)
    }
    fn read_cfg(path: impl AsRef<Path>) -> eyre::Result<Cfg> {
        let path = path.as_ref();
        if let Some(directory) = path.parent() {
            if !directory.exists() {
                fs::create_dir_all(directory)?;
            }
        }
        let res = fs::read_to_string(path);
        let cfg = match res {
            Ok(val) => val,
            Err(err) => {
                type E = io::ErrorKind;
                match err.kind() {
                    E::NotFound => {
                        if !path.exists() {
                            let default = Cfg::default();
                            let json = serde_json::to_string_pretty(&default)?;
                            fs::write(path, json)?;
                            return Ok(default);
                        }
                        return Err(err.into());
                    }
                    _ => return Err(err.into()),
                }
            }
        };
        let cfg = serde_json::from_str(&cfg)?;
        Ok(cfg)
    }
    fn get_now() -> u64 {
        let now = Local::now();
        format!("{}{}{}", now.year(), now.month(), now.day(),)
            .parse::<u64>()
            .unwrap()
    }
    pub fn new(remove_config: bool) -> eyre::Result<Self> {
        let now = Self::get_now();
        let cfg_path = expanduser(format!("~/.config/{PROJECT_NAME}/config.toml"))?;

        let cfg = if remove_config {
            Default::default()
        } else {
            Self::read_cfg(&cfg_path)?
        };

        let last = cfg.last_edit;

        let mut context = Self {
            current_image_path: PathBuf::new(),
            action: Action::Normal,
            domain: "https://www.bing.com/".into(),
            directory: expanduser("~/bing")?,
            desktop_cfg_path: expanduser(
                "~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml",
            )?,
            if_edit: now > last,
            remove_config: false,
        };

        let local = Local::now();
        let image_name = format!("{}-{}-{}.png", local.year(), local.month(), local.day());
        let image_path = context.directory.join(image_name);

        context.current_image_path = image_path;

        fs::write(&cfg_path, serde_json::to_string_pretty(&cfg)?)?;

        Ok(context)
    }
}
